package service

import (
	"admin-nexus-backend/internal/dto"
	"admin-nexus-backend/internal/model"
	"admin-nexus-backend/pkg/logger"
	"encoding/json"
	"time"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// PermissionLogService 权限日志服务
type PermissionLogService struct {
	db *gorm.DB
}

// NewPermissionLogService 创建权限日志服务
func NewPermissionLogService(db *gorm.DB) *PermissionLogService {
	return &PermissionLogService{db: db}
}

// PermissionLogParams 权限日志参数
type PermissionLogParams struct {
	UserID         uint
	Username       string
	ActionType     string // ACCESS, CHANGE, DENY
	PermissionCode string
	ResourceName   string
	Module         string
	Method         string
	Path           string
	IP             string
	UserAgent      string
	Result         int8 // 0-拒绝, 1-通过
	Reason         string
	OldValue       interface{}
	NewValue       interface{}
	OperatorID     uint
	OperatorName   string
	Remark         string
}

// LogPermissionAccess 记录权限访问日志（通过）
func (s *PermissionLogService) LogPermissionAccess(params PermissionLogParams) {
	go s.asyncLogPermission(params)
}

// LogPermissionDeny 记录权限拒绝日志
func (s *PermissionLogService) LogPermissionDeny(params PermissionLogParams) {
	params.ActionType = model.PermissionActionDeny
	params.Result = model.PermissionResultDeny
	go s.asyncLogPermission(params)
}

// LogPermissionChange 记录权限变更日志
func (s *PermissionLogService) LogPermissionChange(params PermissionLogParams) {
	params.ActionType = model.PermissionActionChange
	go s.asyncLogPermission(params)
}

// asyncLogPermission 异步记录权限日志（避免阻塞主流程）
func (s *PermissionLogService) asyncLogPermission(params PermissionLogParams) {
	defer func() {
		if r := recover(); r != nil {
			logger.Error("记录权限日志异常", zap.Any("error", r))
		}
	}()

	log := &model.PermissionLog{
		UserID:         params.UserID,
		Username:       params.Username,
		ActionType:     params.ActionType,
		PermissionCode: params.PermissionCode,
		ResourceName:   params.ResourceName,
		Module:         params.Module,
		Method:         params.Method,
		Path:           params.Path,
		IP:             params.IP,
		UserAgent:      params.UserAgent,
		Result:         params.Result,
		Reason:         params.Reason,
		OperatorID:     params.OperatorID,
		OperatorName:   params.OperatorName,
		Remark:         params.Remark,
		CreatedAt:      time.Now(),
	}

	// 序列化旧值和新值
	if params.OldValue != nil {
		if oldJSON, err := json.Marshal(params.OldValue); err == nil {
			log.OldValue = string(oldJSON)
		}
	}
	if params.NewValue != nil {
		if newJSON, err := json.Marshal(params.NewValue); err == nil {
			log.NewValue = string(newJSON)
		}
	}

	if err := s.db.Create(log).Error; err != nil {
		logger.Error("保存权限日志失败",
			zap.Error(err),
			zap.Uint("userID", params.UserID),
			zap.String("actionType", params.ActionType))
	}
}

// GetPermissionLogs 查询权限日志列表
func (s *PermissionLogService) GetPermissionLogs(params *dto.PermissionLogQueryParams) (*dto.PageResult, error) {
	var logs []model.PermissionLog
	var total int64

	query := s.db.Model(&model.PermissionLog{})

	// 条件过滤
	if params.UserID != nil && *params.UserID > 0 {
		query = query.Where("user_id = ?", *params.UserID)
	}
	if params.Username != "" {
		query = query.Where("username LIKE ?", "%"+params.Username+"%")
	}
	if params.ActionType != "" {
		query = query.Where("action_type = ?", params.ActionType)
	}
	if params.PermissionCode != "" {
		query = query.Where("permission_code LIKE ?", "%"+params.PermissionCode+"%")
	}
	if params.Module != "" {
		query = query.Where("module = ?", params.Module)
	}
	if params.Result != nil {
		query = query.Where("result = ?", *params.Result)
	}
	if params.StartTime != "" {
		query = query.Where("created_at >= ?", params.StartTime)
	}
	if params.EndTime != "" {
		query = query.Where("created_at <= ?", params.EndTime)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, err
	}

	// 分页查询
	offset := (params.Page - 1) * params.PageSize
	if err := query.Offset(offset).Limit(params.PageSize).
		Order("created_at DESC").
		Find(&logs).Error; err != nil {
		return nil, err
	}

	return &dto.PageResult{
		List:     logs,
		Total:    total,
		Page:     params.Page,
		PageSize: params.PageSize,
	}, nil
}

// GetPermissionLogStats 获取权限日志统计
func (s *PermissionLogService) GetPermissionLogStats(days int) (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// 计算时间范围
	startTime := time.Now().AddDate(0, 0, -days)

	// 总访问次数
	var totalCount int64
	s.db.Model(&model.PermissionLog{}).
		Where("created_at >= ?", startTime).
		Count(&totalCount)
	stats["total_count"] = totalCount

	// 成功访问次数
	var successCount int64
	s.db.Model(&model.PermissionLog{}).
		Where("created_at >= ? AND result = ?", startTime, model.PermissionResultAllow).
		Count(&successCount)
	stats["success_count"] = successCount

	// 拒绝访问次数
	var denyCount int64
	s.db.Model(&model.PermissionLog{}).
		Where("created_at >= ? AND result = ?", startTime, model.PermissionResultDeny).
		Count(&denyCount)
	stats["deny_count"] = denyCount

	// 权限变更次数
	var changeCount int64
	s.db.Model(&model.PermissionLog{}).
		Where("created_at >= ? AND action_type = ?", startTime, model.PermissionActionChange).
		Count(&changeCount)
	stats["change_count"] = changeCount

	// TOP 10 最常访问的权限
	type PermissionCount struct {
		PermissionCode string `json:"permissionCode"`
		Count          int64  `json:"count"`
	}
	var topPermissions []PermissionCount
	s.db.Model(&model.PermissionLog{}).
		Select("permission_code, COUNT(*) as count").
		Where("created_at >= ? AND permission_code != ''", startTime).
		Group("permission_code").
		Order("count DESC").
		Limit(10).
		Scan(&topPermissions)
	stats["top_permissions"] = topPermissions

	// TOP 10 最活跃用户
	type UserActivity struct {
		UserID   uint   `json:"userId"`
		Username string `json:"username"`
		Count    int64  `json:"count"`
	}
	var topUsers []UserActivity
	s.db.Model(&model.PermissionLog{}).
		Select("user_id, username, COUNT(*) as count").
		Where("created_at >= ?", startTime).
		Group("user_id, username").
		Order("count DESC").
		Limit(10).
		Scan(&topUsers)
	stats["top_users"] = topUsers

	// 每日统计
	type DailyStats struct {
		Date        string `json:"date"`
		AccessCount int64  `json:"accessCount"`
		DenyCount   int64  `json:"denyCount"`
		ChangeCount int64  `json:"changeCount"`
	}
	var dailyStats []DailyStats
	s.db.Raw(`
		SELECT 
			DATE(created_at) as date,
			SUM(CASE WHEN action_type = 'ACCESS' THEN 1 ELSE 0 END) as access_count,
			SUM(CASE WHEN action_type = 'DENY' THEN 1 ELSE 0 END) as deny_count,
			SUM(CASE WHEN action_type = 'CHANGE' THEN 1 ELSE 0 END) as change_count
		FROM sys_permission_log
		WHERE created_at >= ?
		GROUP BY DATE(created_at)
		ORDER BY date DESC
		LIMIT 30
	`, startTime).Scan(&dailyStats)
	stats["daily_stats"] = dailyStats

	return stats, nil
}

// CleanOldLogs 清理旧日志（保留指定天数）
func (s *PermissionLogService) CleanOldLogs(keepDays int) (int64, error) {
	cutoffTime := time.Now().AddDate(0, 0, -keepDays)

	result := s.db.Where("created_at < ?", cutoffTime).Delete(&model.PermissionLog{})
	if result.Error != nil {
		logger.Error("清理旧权限日志失败", zap.Error(result.Error), zap.Int("keepDays", keepDays))
		return 0, result.Error
	}

	logger.Info("清理旧权限日志成功", zap.Int64("deletedCount", result.RowsAffected), zap.Int("keepDays", keepDays))
	return result.RowsAffected, nil
}

// GetUserPermissionHistory 获取用户权限变更历史
func (s *PermissionLogService) GetUserPermissionHistory(userID uint, limit int) ([]model.PermissionLog, error) {
	var logs []model.PermissionLog
	err := s.db.Where("user_id = ? AND action_type = ?", userID, model.PermissionActionChange).
		Order("created_at DESC").
		Limit(limit).
		Find(&logs).Error

	return logs, err
}
